package com.luhuiguo.cms.client.presenter;

import com.extjs.gxt.ui.client.binding.FormBinding;
import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.data.BeanModelFactory;
import com.extjs.gxt.ui.client.data.BeanModelLookup;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.FormPanel;
import com.extjs.gxt.ui.client.widget.form.HtmlEditor;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.inject.Inject;
import com.luhuiguo.cms.client.GlobalConstants;
import com.luhuiguo.cms.client.GlobalMessages;
import com.luhuiguo.cms.shared.event.ArticleCreatedEvent;
import com.luhuiguo.cms.shared.event.ArticleUpdatedEvent;
import com.luhuiguo.cms.shared.event.EditArticleCancelledEvent;
import com.luhuiguo.cms.shared.event.LoadAttachmentsEvent;
import com.luhuiguo.cms.shared.event.LoadAttachmentsEventHandler;
import com.luhuiguo.cms.shared.model.ArticleModel;
import com.luhuiguo.cms.shared.rpc.CreateArticle;
import com.luhuiguo.cms.shared.rpc.CreateArticleResult;
import com.luhuiguo.cms.shared.rpc.RemoveDraftArticles;
import com.luhuiguo.cms.shared.rpc.RemoveDraftArticlesResult;
import com.luhuiguo.cms.shared.rpc.UpdateArticle;
import com.luhuiguo.cms.shared.rpc.UpdateArticleResult;
import com.luhuiguo.gwt.dispatcher.client.DispatcherAsync;
import com.luhuiguo.gwt.presenter.client.EventBus;
import com.luhuiguo.gwt.presenter.client.widget.WidgetContainerDisplay;
import com.luhuiguo.gwt.presenter.client.widget.WidgetContainerPresenter;

public class EditArticlePresenter extends WidgetContainerPresenter<EditArticlePresenter.Display> {

    public interface Display extends WidgetContainerDisplay {

        FormPanel getFormPanel();

        FormBinding getFormBinding();

        Button getSubmitButton();

        Button getCancelButton();

        HtmlEditor getHtmlEditor();

    }

    private DispatcherAsync dispatcher;

    @SuppressWarnings("unused")
    private GlobalConstants constants;

    private GlobalMessages messages;

    private ArticleModel articleModel;

    private AttachmentsPresenter attachmentsPresenter;

    @Inject
    public EditArticlePresenter(Display display, EventBus eventBus, DispatcherAsync dispatcher,
            GlobalConstants constants, GlobalMessages messages, AttachmentsPresenter attachmentsPresenter) {
        super(display, eventBus, attachmentsPresenter);
        this.dispatcher = dispatcher;
        this.constants = constants;
        this.messages = messages;

        this.attachmentsPresenter = attachmentsPresenter;

    }

    @Override
    protected void onBind() {

        GWT.log("binding EditArticlePresenter");

        super.onBind();

        registerHandler(eventBus.addHandler(LoadAttachmentsEvent.TYPE, new LoadAttachmentsEventHandler() {

            @Override
            public void onLoadAttachments(LoadAttachmentsEvent event) {
                attachmentsPresenter.revealDisplay(event.getArticleId());
            }

        }));

        display.getCancelButton().addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                removeDraft();

                // eventBus.fireEvent(new
                // EditArticleCancelledEvent(articleModel.getChannelId()));
            }
        });

        display.getSubmitButton().addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                if (display.getFormPanel().isValid()) {
                    display.getFormPanel().mask();
                    articleModel.setContent(display.getHtmlEditor().getValue());
                    if (null == articleModel.getId()) {
                        createArticle();
                    } else {
                        updateArticle();
                    }
                }
            }
        });

    }

    protected void removeDraft() {
        dispatcher.execute(new RemoveDraftArticles(), new AsyncCallback<RemoveDraftArticlesResult>() {

            @Override
            public void onFailure(Throwable caught) {
                MessageBox.alert(messages.error(), messages.deleteArticlesFailed(), null);
                eventBus.fireEvent(new EditArticleCancelledEvent(articleModel.getChannelId()));
            }

            @Override
            public void onSuccess(RemoveDraftArticlesResult result) {
                eventBus.fireEvent(new EditArticleCancelledEvent(articleModel.getChannelId()));
            }
        });

    }

    protected void updateArticle() {
        dispatcher.execute(new UpdateArticle(articleModel), new AsyncCallback<UpdateArticleResult>() {

            @Override
            public void onFailure(Throwable caught) {
                display.getFormPanel().unmask();
                MessageBox.alert(messages.error(), messages.saveArticleFailed(articleModel.getTitle()), null);
            }

            @Override
            public void onSuccess(UpdateArticleResult result) {
                display.getFormPanel().unmask();
                eventBus.fireEvent(new ArticleUpdatedEvent(result.getNew()));

            }
        });

    }

    protected void createArticle() {
        dispatcher.execute(new CreateArticle(articleModel), new AsyncCallback<CreateArticleResult>() {

            @Override
            public void onFailure(Throwable caught) {
                display.getFormPanel().unmask();
                MessageBox.alert(messages.error(), messages.saveArticleFailed(articleModel.getTitle()), null);
            }

            @Override
            public void onSuccess(CreateArticleResult result) {
                display.getFormPanel().unmask();
                eventBus.fireEvent(new ArticleCreatedEvent(result.get()));

            }
        });

    }

    protected void revealDisplay(ArticleModel articleModel) {
        this.articleModel = articleModel;

        BeanModelFactory factory = BeanModelLookup.get().getFactory(ArticleModel.class);
        BeanModel model = factory.createModel(articleModel);

        display.getFormBinding().bind(model);
        display.getHtmlEditor().setValue(articleModel.getContent());
        eventBus.fireEvent(new LoadAttachmentsEvent(articleModel.getId()));
        revealDisplay();
    }

}
